#include "stdafx.h"
#include "ui_window_manager.h"
#include <WindowsX.h>
#include <commctrl.h>
#pragma comment(lib, "comctl32.lib")

#include "ui_focusable_control.h"

_SSL_BEGIN
_SSUIL_BEGIN

#define kInternalTimerID 0x1215
#define kInternalTimerInterval 20

UIWindowManager::UIWindowManager()
{
	hwnd_ = NULL;
	hinst_ = NULL;
	// notify_receivers_
	// message_filters_
	// focus_change_listeners_
	// root_
	// background_canvas_
	// resource_render_
	// disk_files_manager_
	// ui_builder_

	// timers_lock_
	// timers_

	message_begin_ = false;
	// invalidated_rt_
	translucent_ = false;
	// preset_bg_img_
	// noalpha_control_name_
	full_screen_ = false;

	// data_lock_
	// async_notifies_

	// pressed_control_
	// overed_control_
	// focused_control_

	mouse_track_last_tick_ = 0;
	mouse_tracking_ = false;
	// last_mouse_position_
	// last_mouse_position_for_hover_
	// win_func_wrapper_
	mouse_captured_ = false;
	mouse_wheel_delta_ = 0;
	mouse_wheel_timer_ = 0;
	// mouse_wheel_evts_
	mouse_wheel_global_speed_ = 0;
	// mouse_wheel_evt_lock_
}

UIWindowManager::~UIWindowManager()
{

}

bool UIWindowManager::Init(
	HWND hwnd,
	HINSTANCE inst,
	IUIWindowBgCanvasInterface *background_canvas,
	IUIResourceRenderInterface *res_render,
	IUIDiskFilesManagerInterface *disk_manager,
	IUIBuilderInterface *builder
	)
{
	if(!::IsWindow(hwnd) || background_canvas == NULL
		|| res_render == NULL || disk_manager == NULL)
		return false;

	hwnd_ = hwnd;
	hinst_ = inst;
	root_ = NULL;
	background_canvas_ = background_canvas;
	SS_VERIFY(background_canvas_->Init(hwnd));
	resource_render_ = res_render;
	resource_render_->SetDiskFilesManager(disk_manager);
	disk_files_manager_ = disk_manager;
	ui_builder_ = builder;
	return true;
}

void UIWindowManager::Uninit()
{
	disk_files_manager_ = NULL;
	if(resource_render_ != NULL)
	{
		resource_render_->SetDiskFilesManager(NULL);
		resource_render_ = NULL;
	}
	if(background_canvas_ != NULL)
	{
		background_canvas_->Uninit();
		background_canvas_ = NULL;
	}
	root_ = NULL;
	hinst_ = NULL;
	hwnd_ = NULL;
}

bool UIWindowManager::IsTranslucent()
{
	return translucent_;
}

void UIWindowManager::SetBackgroundImage(UIPresetImage &bg, bool translucent /*= false*/)
{
	preset_bg_img_ = bg;
	if(preset_bg_img_.image_name.empty())
	{
		translucent = false;
	}
	translucent_ = translucent;

	if(translucent_)
	{
		::SetWindowLong(hwnd_, GWL_EXSTYLE,
			::GetWindowLong(hwnd_, GWL_EXSTYLE)|WS_EX_LAYERED);
	}else
	{
		::SetWindowLong(hwnd_, GWL_EXSTYLE,
			::GetWindowLong(hwnd_, GWL_EXSTYLE)&~WS_EX_LAYERED);
	}
	if(background_canvas_ != NULL)
	{
		background_canvas_->SetBackgroundImage(preset_bg_img_);
	}

	Recalc();
}

void UIWindowManager::SetNoalphaControlOnTranslucentMode(const tstring &control_name)
{
	noalpha_control_name_ = control_name;
}

void UIWindowManager::SetTransparentColor(unsigned long color)
{
	HWND window = hwnd_;
	if(color == INVALID_DWORD_COLOR_VALUE)
	{
		LONG ex_style = GetWindowLong(window, GWL_EXSTYLE);
		ex_style &= ~WS_EX_LAYERED;
		SetWindowLong(window, GWL_EXSTYLE, ex_style);
	}else
	{
		LONG ex_style = GetWindowLong(window, GWL_EXSTYLE);
		ex_style |= WS_EX_LAYERED;
		::SetWindowLong(window, GWL_EXSTYLE, ex_style);
		::SetLayeredWindowAttributes(window, 
			RGB(GetBValue(color), GetGValue(color), GetRValue(color)), 0, LWA_COLORKEY);
		background_canvas_->SetTransparentColor(color);
	}
}

scoped_ref_ptr<IUIWindowBgCanvasInterface> UIWindowManager::GetBackgroundBgCanvas()
{
	return background_canvas_;
}

void UIWindowManager::SetFullScreen(bool f)
{
	full_screen_ = f;
}

bool UIWindowManager::IsFullScreen()
{
	return full_screen_;
}

HWND UIWindowManager::GetWindow()
{
	return hwnd_;
}

bool UIWindowManager::SetFocus(IUIControlInterface *control)
{
	UIFocusableControl *focusable_control = NULL;
	if(control != NULL)
	{
		focusable_control = (dynamic_cast<UIFocusableControl*>(control));
		if(focusable_control == NULL)
		{
			return false;
		}
		if(!focusable_control->IsFocusSensitive())
		{
			return false;
		}
	}

	IUIControlInterface *focus_control = focused_control_.get();
	focused_control_.reset();

	if(focus_control != NULL)
	{
		focus_control->OnStateChangedCB();
		focus_control->Invalidate();
	}

	if(control == NULL)
	{
		FocusChangedNotify(focus_control, NULL);
		return true;
	}

	focused_control_ = control->as_weak_ptr();

	if(focusable_control != NULL)
	{
		focusable_control->OnStateChangedCB();
		focusable_control->Invalidate();
	}

	UINotify nty;
	nty.type = _T("focus_changed");
	nty.sender = focus_control;
	SendNotify(nty);
	FocusChangedNotify(focus_control, focused_control_.get());
	return true;
}

bool UIWindowManager::KillFocus(IUIControlInterface *control)
{
	if(control != focused_control_.get())
		return false;

	scoped_ref_ptr<IUIControlInterface> focus_control = focused_control_.get();
	focused_control_.reset();
	if(focus_control != NULL)
		focus_control->Invalidate();

	return true;
}

scoped_ref_ptr<IUIControlInterface> UIWindowManager::GetFocusControl()
{
	return focused_control_.get();
}

bool UIWindowManager::SetCapture()
{
	mouse_captured_ = BOOL2bool(::SetCapture(hwnd_));
	return mouse_captured_;
}

bool UIWindowManager::IsCaptured()
{
	return mouse_captured_;
}

void UIWindowManager::ReleaseCapture()
{
	::ReleaseCapture();
	mouse_captured_ = false;
}

bool UIWindowManager::AppendUINotifyReceiver(IUINotifyReceiverInterface *receiver)
{
	if(receiver == NULL)
		return false;

	IUINotifyReceiverInterfaceAutoPtrs::iterator iter = std::find(
		notify_receivers_.begin(), notify_receivers_.end(), receiver);
	if(iter != notify_receivers_.end())
		return false;
	notify_receivers_.push_back(receiver);
	return true;
}

bool UIWindowManager::RemoveUINotifyReceiver(IUINotifyReceiverInterface *receiver)
{
	if(receiver == NULL)
		return false;

	IUINotifyReceiverInterfaceAutoPtrs::iterator iter = std::find(
		notify_receivers_.begin(), notify_receivers_.end(), receiver);
	if(iter == notify_receivers_.end())
		return false;
	notify_receivers_.erase(iter);
	return true;
}

bool UIWindowManager::AppendMessageFilter(IUIMessageFilterInterface *filter)
{
	if(filter == NULL)
		return false;

	IUIMessageFilterInterfaceAutoPtrs::iterator iter = std::find(
		message_filters_.begin(), message_filters_.end(), filter);
	if(iter != message_filters_.end())
		return false;
	message_filters_.push_back(filter);
	return true;
}

bool UIWindowManager::RemoveMessageFilter(IUIMessageFilterInterface *filter)
{
	if(filter == NULL)
		return false;

	IUIMessageFilterInterfaceAutoPtrs::iterator iter = std::find(
		message_filters_.begin(), message_filters_.end(), filter);
	if(iter == message_filters_.end())
		return false;
	message_filters_.erase(iter);
	return true;
}

bool UIWindowManager::AppendFocusChangeListener(IUIFocusChangeListenerInterface *listener)
{
	if(listener == NULL)
		return false;

	IUIFocusChangeListenerInterfaceAutoPtrs::iterator iter = std::find(
		focus_change_listeners_.begin(), focus_change_listeners_.end(), listener);
	if(iter != focus_change_listeners_.end())
		return false;
	focus_change_listeners_.push_back(listener);
	return true;
}

bool UIWindowManager::RemoveFocusChangeListener(IUIFocusChangeListenerInterface *listener)
{
	if(listener == NULL)
		return false;

	IUIFocusChangeListenerInterfaceAutoPtrs::iterator iter = std::find(
		focus_change_listeners_.begin(), focus_change_listeners_.end(), listener);
	if(iter == focus_change_listeners_.end())
		return false;
	focus_change_listeners_.erase(iter);
	return true;
}

scoped_ref_ptr<IUIControlInterface> UIWindowManager::SetContent(IUIControlInterface *content)
{
	scoped_ref_ptr<IUIControlInterface> ret = root_;
	root_ = content;
	if(root_.get())
	{
		root_->SetDirectUIManager(this);
	}
	if(ret.get())
	{
		ret->SetDirectUIManager(NULL);
	}
	Invalidate(NULL);
	return ret;
}

scoped_ref_ptr<IUIControlInterface> UIWindowManager::GetContent()
{
	return root_;
}

bool UIWindowManager::HandleMessage(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT &lret)
{
	bool ret = false;
	message_begin_ = true;
	invalidated_rt_.SetEmpty();

	ProcessAsyncNotifies();

	for(IUIMessageFilterInterfaceAutoPtrs::iterator iter = message_filters_.begin();
		iter != message_filters_.end(); iter++)
	{
		bool handled = false;
		LRESULT ret = (*iter)->MessageHandle(this, msg, wparam, lparam, handled);
		if(handled)
		{
			lret = ret;
			return true;
		}
	}

	switch(msg)
	{
	case WM_ACTIVATE:
		ret = HandleActivateMessage(msg, wparam, lparam, lret);
		break;
	case WM_NCACTIVATE:
		lret = TRUE;
		return true;
	case WM_ERASEBKGND:
		lret = 0;
		return true;
	case WM_PAINT:
		ret = HandlePaintMessage(msg, wparam, lparam, lret);
		break;
	case WM_SIZE:
		ret = HandleSizeMessage(msg, wparam, lparam, lret);
		break;
	case WM_TIMER:
		ret = HandleTimerMessage(msg, wparam, lparam, lret);
		break;
	case WM_GETMINMAXINFO:
		ret = HandleGetMinMaxInfoMessage(msg,wparam, lparam, lret);
		break;
	case WM_SETCURSOR:
		ret = HandleSetCursorMessage(msg,wparam, lparam, lret);
		break;
	case WM_LBUTTONDOWN:
	case WM_RBUTTONDOWN:
		ret = HandleMouseButtonDownMessage(msg,wparam, lparam, lret);
		break;
	case WM_LBUTTONUP:
	case WM_RBUTTONUP:
		ret = HandleMouseButtonUpMessage(msg,wparam, lparam, lret);
		break;
	case WM_MOUSEMOVE:
		ret = HandleMouseMoveMessage(msg,wparam, lparam, lret);
		break;
	case WM_MOUSELEAVE:
		ret = HandleMouseLeaveMessage(msg,wparam, lparam, lret);
		break;
	case WM_MOUSEWHEEL:
		ret = HandleMouseWheelMessage(msg,wparam, lparam, lret);
		break;
	case WM_KEYDOWN:
		ret = HandleKeyDownMessage(msg,wparam, lparam, lret);
		break;
	}
	message_begin_ = false;

	ProcessAsyncNotifies();

	if(!invalidated_rt_.IsEmptry())
	{
		Invalidate(&invalidated_rt_);
		invalidated_rt_.SetEmpty();
	}
	return ret;
}

void UIWindowManager::Invalidate(const RECT *rt)
{
	if(message_begin_ && rt != NULL)
	{
		UIRect rtt(*rt);
		invalidated_rt_.UnionRect(invalidated_rt_, rtt);
	}else
	{
		::InvalidateRect(hwnd_, rt, FALSE);
	}
}

bool UIWindowManager::SetTimer(IUITimerInterface *timer)
{
	if(timer == NULL)
		return false;
	CsLockGuard(timers_lock_);
	IUITimerInterfaceAutoPtrs::iterator iter = std::find(timers_.begin(), timers_.end(), timer);
	if(iter == timers_.end())
	{
		timers_.push_back(timer);
		if(timers_.size() == 1)
		{
			SS_VERIFY(::SetTimer(hwnd_, kInternalTimerID, kInternalTimerInterval, NULL));
		}
	}
	return true;
}

bool UIWindowManager::KillTimer(IUITimerInterface *timer)
{
	if(timer == NULL)
		return false;
	CsLockGuard(timers_lock_);
	IUITimerInterfaceAutoPtrs::iterator iter = std::find(timers_.begin(), timers_.end(), timer);
	if(iter == timers_.end())
		return false;
	timers_.erase(iter);
	if(timers_.empty())
	{
		::KillTimer(hwnd_, kInternalTimerID);
	}
	return true;
}

HINSTANCE UIWindowManager::GetInstance()
{
	return hinst_;
}

scoped_ref_ptr<IUIResourceRenderInterface> UIWindowManager::GetResourceRener()
{
	return resource_render_;
}

scoped_ref_ptr<IUIDiskFilesManagerInterface> UIWindowManager::GetDiskFilesManager()
{
	return disk_files_manager_;
}

scoped_ref_ptr<IUIBuilderInterface> UIWindowManager::GetBuilder()
{
	return ui_builder_;
}

void UIWindowManager::SendNotify(UINotify &notify)
{
	CsLockGuard(data_lock_);
	async_notifies_.push(notify);
	::PostMessage(hwnd_, WM_NULL, 0, 0);
}

UIRect UIWindowManager::RecalcLayout()
{
	UIRect rt;
	if(root_.get() == NULL)
		return rt;
	if(background_canvas_.get() == NULL)
		return rt;

	if(root_->NeedUpdate())
	{
		UIControl_SetPostion(UISize(background_canvas_->GetWidth(),background_canvas_->GetHeight()),
			UIRect(0,0,background_canvas_->GetWidth(),background_canvas_->GetHeight()), root_.get());
		rt.left = 0;
		rt.top = 0;
		rt.right = background_canvas_->GetWidth();
		rt.bottom = background_canvas_->GetHeight();
	}else
	{
		scoped_ref_ptr<IUIControlInterface> control;
		while((control = root_->FindControl(__FindControlForUpdate, NULL, kUIFindMeFirst|kUIFindVisibled)) != NULL)
		{
			rt.UnionRect(rt, control->GetPositionOnClient());
			if(control->GetParent() != NULL)
				control->GetParent()->LayoutChilds();
			else
				control->LayoutChilds();
			control->SetNeedUpdate(false);
			rt.UnionRect(rt, control->GetPositionOnClient());
		}
	}
	return rt;
}

void UIWindowManager::Recalc()
{
	if(root_ != NULL)
	{
		root_->SetNeedUpdate(true);
	}
}

void UIWindowManager::DoEvent(UIEvent &evt)
{

}

void UIWindowManager::OnTimerCB(unsigned int timer_id)
{
	if(timer_id == mouse_wheel_timer_)
	{
		CsLockGuard(mouse_wheel_evt_lock_);

		UIMouseWheelDir mouse_wheel_evt_cur_ = kMWDirNone;

		size_t evts_cnt_ = mouse_wheel_evts_.size();
		if(evts_cnt_ == 0)
		{
			KillIDTimer(mouse_wheel_timer_);
			mouse_wheel_timer_ = 0;
			mouse_wheel_global_speed_ = 0;
			return;
		}

		mouse_wheel_global_speed_ += 5;

		scoped_ref_ptr<IUIControlInterface> mouse_wheel_control = GetMouseWheelReceiverControl(last_mouse_position_);
		if(mouse_wheel_control == NULL)
		{
			mouse_wheel_global_speed_ = 0;
			mouse_wheel_evts_.clear();
			evts_cnt_ = 0;
		}else
		{
			mouse_wheel_evt_cur_ = *mouse_wheel_evts_.begin();
		}

		if(evts_cnt_ > 0)
		{
			mouse_wheel_evts_.erase(mouse_wheel_evts_.begin());
			evts_cnt_--;
		}

		if(evts_cnt_ == 0)
		{
			SetIDTimer(mouse_wheel_timer_, 300);
		}

		if(mouse_wheel_control != NULL && mouse_wheel_evt_cur_ != kMWDirNone)
		{
			UIEvent evt;
			evt.mouse_point = last_mouse_position_;

			evt.type = kEvtMouseWheel;
			evt.key_state = mouse_wheel_evt_cur_;
			evt.wparam = mouse_wheel_global_speed_;
			evt.relative_control = mouse_wheel_control;
			mouse_wheel_control->DispatchEventOfControl(evt);
			TraceVD(_T("global speed : %d\n"), mouse_wheel_global_speed_);
		}
	}
}

void UIWindowManager::TrySetTimerOnWindowManager()
{
	SetTimer(this);
}

void UIWindowManager::KillTimerOnWindowManager()
{
	KillTimer(this);
}

bool UIWindowManager::HandleActivateMessage(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT &lret)
{
	if(LOWORD(wparam) != WA_INACTIVE)
		return false;

	mouse_captured_ = false;
	::ReleaseCapture();

	scoped_ref_ptr<IUIControlInterface> pressed_control = pressed_control_.get();
	if(pressed_control != NULL)
	{
		UIEvent evt;
		evt.type = kEvtButtonUp;
		evt.wparam = WM_NULL;
		ControlDispatchEvent(pressed_control, evt);

		pressed_control_.reset();
	}

	scoped_ref_ptr<IUIControlInterface> overed_control = overed_control_.get();
	if(overed_control != NULL)
	{
		UIEvent evt;
		evt.type = kEvtMouseLeave;
		ControlDispatchEvent(overed_control, evt);

		overed_control_.reset();
	}

	return false;
}

bool UIWindowManager::HandlePaintMessage(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT &lret)
{
	if(background_canvas_ == NULL)
		return false;
	if(root_ == NULL)
		return false;

	RecalcLayout();

	UIRenderStruct rs;
	rs.type = kDCTypeOnMessage;
	rs.dct_message_parameters.rr = resource_render_;
	rs.dct_message_parameters.msg = msg;
	rs.dct_message_parameters.wparam = wparam;
	rs.dct_message_parameters.lparam = lparam;
	if(translucent_)
	{
		scoped_ref_ptr<IUIControlInterface> noalpha_control;
		if(!noalpha_control_name_.empty())
			noalpha_control = root_->FindControl(noalpha_control_name_.c_str());

		if(noalpha_control != NULL)
		{
			UIRect na_pos = noalpha_control->GetPositionOnClient();
			if(na_pos.left < 0)
				na_pos.left = 0;
			if(na_pos.top < 0)
				na_pos.top = 0;
			if(na_pos.right > background_canvas_->GetWidth())
				na_pos.right = background_canvas_->GetWidth();
			if(na_pos.bottom > background_canvas_->GetHeight())
				na_pos.bottom = background_canvas_->GetHeight();
			background_canvas_->SetAlphaMode(translucent_, UIRect(na_pos.left, na_pos.top,
				background_canvas_->GetWidth() - na_pos.right, background_canvas_->GetHeight() - na_pos.bottom));
		}else
		{
			background_canvas_->SetAlphaMode(translucent_, UIRect());
		}
	}else
	{
		background_canvas_->SetAlphaMode(false, UIRect());
	}

	void *dc = background_canvas_->BeginRender(rs);
	root_->Render(dc, UIRect(0, 0, background_canvas_->GetWidth(), background_canvas_->GetHeight()));
	background_canvas_->EndRender(dc);
	dc = NULL;

	lret = 0;
	return true;
}

bool UIWindowManager::HandleSizeMessage(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT &lret)
{
	if(background_canvas_ != NULL)
		background_canvas_->WindowResized();
	if(root_ != NULL)
		root_->SetNeedUpdate(true);
	return true;
}

bool UIWindowManager::HandleTimerMessage(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT &lret)
{
	if(wparam == kInternalTimerID)
	{
		IUITimerInterfaceAutoPtrs timers;
		timers_lock_.enter();
		timers = timers_;
		timers_lock_.leave();
		for(IUITimerInterfaceAutoPtrs::iterator iter=timers.begin(); iter!=timers.end(); iter++)
		{
			(*iter)->OnTimer(kInternalTimerInterval);
		}
		lret = 0;
		return true;
	}
	return false;
}

bool UIWindowManager::HandleGetMinMaxInfoMessage(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT &lret)
{
	PMINMAXINFO min_max_info = (MINMAXINFO*)lparam;
	if(min_max_info == NULL)
		return false;

	if(!full_screen_)
	{
		UIRect work_area;
		SystemParametersInfo(SPI_GETWORKAREA, 0, &work_area, 0);
		if(!::IsRectEmpty(&work_area))
		{
			min_max_info->ptMaxSize.x = work_area.Width();
			min_max_info->ptMaxTrackSize.x = work_area.Width();
			min_max_info->ptMaxSize.y = work_area.Height();
			min_max_info->ptMaxTrackSize.y = work_area.Height();
			lret = 0L;
			return true;
		}
	}

	return false;
}

bool UIWindowManager::HandleSetCursorMessage(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT &lret)
{
	scoped_ref_ptr<IUIControlInterface> top_root = root_;
	if(top_root == NULL)
		return false;

	UIPoint mouse_position;
	::GetCursorPos(&mouse_position);
	::ScreenToClient(hwnd_, &mouse_position);
	last_mouse_position_ = mouse_position;

	UIFindControlByPoint find_data;
	find_data.pt = mouse_position;
	find_data.for_cursor = true;
	scoped_ref_ptr<IUIControlInterface> over_control = top_root->FindControl(find_data);
	if(over_control == NULL)
		return false;

	UIEvent evt;
	evt.mouse_point = mouse_position;
	evt.type = kEvtSetCursor;

	ControlDispatchEvent(over_control.get(), evt);

	if(evt.lret != 0)
	{
		lret = evt.lret;
		return true;
	}

	return false;
}

bool UIWindowManager::HandleMouseButtonDownMessage(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT &lret)
{
	SS_ASSERT(msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN);

	scoped_ref_ptr<IUIControlInterface> top_root = root_;
	if(top_root == NULL)
		return false;

	::SetFocus(hwnd_);

	UIPoint mouse_position(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam));
	last_mouse_position_ = mouse_position;

	UIFindControlByPoint find_data;
	find_data.pt = mouse_position;
	find_data.for_focus = true;

	scoped_ref_ptr<IUIControlInterface> focus_control = top_root->FindControl(find_data);
	if(focus_control != NULL)
	{
		SetFocus(focus_control);
	}

	find_data.Reset();
	find_data.for_press = true;
	scoped_ref_ptr<IUIControlInterface> pressed_control = top_root->FindControl(find_data);
	if(pressed_control == NULL)
	{
		return false;
	}

	if(pressed_control == pressed_control_.get())
		return false;


	UIEvent evt;
	evt.mouse_point = mouse_position;
	evt.type = kEvtButtonUp;
	evt.wparam = WM_NULL;
	ControlDispatchEvent(pressed_control_.get(), evt);
	pressed_control_.reset();

	SetCapture();

	evt.type = ((msg == WM_LBUTTONDOWN) ? kEvtLButtonDown : kEvtRButtonDown);
	pressed_control_ = pressed_control->as_weak_ptr();
	ControlDispatchEvent(pressed_control_.get(), evt);

	return false;
}

bool UIWindowManager::HandleMouseButtonUpMessage(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT &lret)
{
	SS_ASSERT(msg == WM_LBUTTONUP || msg == WM_RBUTTONUP);

	scoped_ref_ptr<IUIControlInterface> top_root = root_;
	if(top_root == NULL)
		return false;

	UIPoint mouse_position(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam));
	last_mouse_position_ = mouse_position;

	if(pressed_control_ == NULL)
		return false;

	ReleaseCapture();

	UIEvent evt;
	evt.mouse_point = mouse_position;
	scoped_ref_ptr<IUIControlInterface> pressed_control = dynamic_cast<IUIControlInterface*>(pressed_control_.get());
	if(pressed_control != NULL)
	{
		evt.type = kEvtButtonUp;
		evt.wparam = msg;
		UIFindControlByPoint find_data;
		find_data.pt = mouse_position;
		find_data.for_press = true;
		evt.relative_control = top_root->FindControl(find_data);
		ControlDispatchEvent(pressed_control, evt);
	}
	pressed_control_.reset();

	return false;
}

bool UIWindowManager::HandleMouseMoveMessage(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT &lret)
{
	scoped_ref_ptr<IUIControlInterface> top_root = root_;
	if(top_root == NULL)
		return false;

	if(mouse_tracking_)
	{
		if(win_func_wrapper_.GetTickCount64 != NULL)
		{
			if(win_func_wrapper_.GetTickCount64() - mouse_track_last_tick_ > 1000)
			{
				mouse_track_last_tick_ = win_func_wrapper_.GetTickCount64();
				mouse_tracking_ = false;
			}
		}else
		{
			if((__int64)::GetTickCount() - mouse_track_last_tick_ > 1000)
			{
				mouse_track_last_tick_ = (__int64)::GetTickCount();
				mouse_tracking_ = false;
			}
		}

	}
	if(!mouse_tracking_)
	{
		TRACKMOUSEEVENT tme = {0};
		tme.cbSize = sizeof(tme);
		tme.dwFlags = TME_LEAVE;
		tme.hwndTrack = hwnd_;
		mouse_tracking_ = _TrackMouseEvent(&tme) ? true : false;
	}

	UIPoint mouse_position(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam));
	last_mouse_position_ = mouse_position;
	UIFindControlByPoint find_data;
	find_data.pt = mouse_position;

	if(pressed_control_ == NULL)
	{
		// TBI : 
/*
		hittest_data.for_tooltip = true;
		base_control_interface *tooltip_control = top_root->find_control(find_control_for_hittest,
			&hittest_data, UIFIND_ENABLED|UIFIND_VISIBLED|UIFIND_TOP_FIRST|UIFIND_HITTEST);
		if(tooltip_control != tooltip_host_control_)
		{
			to_show_tooltip(tooltip_control);
		}else if(tooltip_host_control_ != NULL)
		{
			to_show_tooltip(tooltip_host_control_);
		}
*/
	}

	find_data.Reset();
	find_data.for_over = true;
	scoped_ref_ptr<IUIControlInterface> over_control = top_root->FindControl(find_data);

	UIEvent evt;
	evt.mouse_point = mouse_position;

	scoped_ref_ptr<IUIControlInterface> overed_control_old = dynamic_cast<IUIControlInterface*>(overed_control_.get());
	if(overed_control_old != NULL && !overed_control_old->compare(over_control))
	{
		evt.type = kEvtMouseLeave;
		ControlDispatchEvent(overed_control_old, evt);
		overed_control_.reset();
	}

	if(over_control != NULL && !over_control->compare(overed_control_old))
	{
		evt.type = kEvtMouseEnter;
		overed_control_ = over_control->as_weak_ptr();
		ControlDispatchEvent(overed_control_.get(), evt);
	}

	if(overed_control_ != NULL)
	{
		evt.type = kEvtMouseMove;
		ControlDispatchEvent(overed_control_.get(), evt);
	}

	if(pressed_control_ != NULL && !pressed_control_->compare(overed_control_.get()))
	{
		evt.type = kEvtMouseMove;
		ControlDispatchEvent(pressed_control_.get(), evt);
	}

	return false;
}

bool UIWindowManager::HandleMouseLeaveMessage(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT &lret)
{
	if(mouse_tracking_)
	{
		::SendMessage(hwnd_, WM_MOUSEMOVE, 0, (LPARAM)-1);
		mouse_tracking_ = false;
	}
	return false;
}

bool UIWindowManager::HandleMouseWheelMessage(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT &lret)
{
	if(root_ == NULL)
		return false;

	UIPoint mouse_position(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam));
	::ScreenToClient(hwnd_, &mouse_position);

	UIMouseWheelDir mwt = kMWDirNone;

	mouse_wheel_delta_ += GET_WHEEL_DELTA_WPARAM(wparam);
	if(mouse_wheel_delta_ >= WHEEL_DELTA)
	{
		mwt = kMWDirUp;
	}else if(mouse_wheel_delta_ <= -WHEEL_DELTA)
	{
		mwt = kMWDirDown;
	}

	if(mwt == kMWDirNone)
		return false;

	mouse_wheel_delta_ = 0;

	last_mouse_position_ = mouse_position;
	if(GetMouseWheelReceiverControl(mouse_position) != NULL)
	{
		MouseWheelTrigger(mwt);
	}
	return false;
}

bool UIWindowManager::HandleKeyDownMessage(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT &lret)
{
	//if(wparam == VK_TAB)
	//{
	//	set_next_tab_control(::GetKeyState(VK_SHIFT) >= 0);
	//	return false;
	//}

	//if(wparam == VK_RETURN)
	//{
	//	if(focused_control_ != NULL)
	//		focused_control_->DoAction();
	//	return false;
	//}

	if(wparam >= VK_PRIOR && wparam <= VK_DOWN)
	{
		scoped_ref_ptr<IUIControlInterface> arrowkey_control = GetArrowkeyReceiverControl();
		if(arrowkey_control != NULL)
		{
			UIEvent evt;
			evt.type = kEvtKeyDown;
			evt.key_character = wparam;
			arrowkey_control->DispatchEventOfControl(evt);
			return false;
		}
	}

	return false;
}

scoped_ref_ptr<IUIControlInterface> UIWindowManager::GetMouseWheelReceiverControl(const UIPoint &pt)
{
	if(root_ == NULL)
		return NULL;

	UIFindControlByPoint find_data;
	find_data.pt = pt;
	scoped_ref_ptr<IUIControlInterface> control = root_->FindControl(find_data);
	while(control != NULL && !SS_FLAG_ISSET(control->GetProperties(), kControlPropertyAcceptMouseWheel))
	{
		control = control->GetParent();
	}
	return control;
}

scoped_ref_ptr<IUIControlInterface> UIWindowManager::GetArrowkeyReceiverControl()
{
	scoped_ref_ptr<IUIControlInterface> control = focused_control_.get();
	while(control != NULL && !SS_FLAG_ISSET(control->GetProperties(), kControlPropertyAcceptArrowKey))
	{
		control = control->GetParent();
	}
	return control;
}

bool UIWindowManager::ControlDispatchEvent(IUIControlInterface *control, UIEvent &evt)
{
	scoped_ref_ptr<IUIEventReceiverInterface> evt_receiver = dynamic_cast<IUIEventReceiverInterface*>(control);
	if(evt_receiver == NULL)
		return false;
	evt_receiver->DispatchEvent(evt);
	return true;
}

void UIWindowManager::FocusChangedNotify(IUIControlInterface *focused_before, IUIControlInterface *focused_now)
{
	IUIFocusChangeListenerInterfaceAutoPtrs listener_cloned;

	{
		CsLockGuard(data_lock_);
		listener_cloned = focus_change_listeners_;
	}

	for(IUIFocusChangeListenerInterfaceAutoPtrs::iterator iter = listener_cloned.begin();
		iter != listener_cloned.end(); iter++)
	{
		if(*iter == NULL)
			continue;
		(*iter)->OnFocusChanged(focused_before, focused_now);
	}
}

void UIWindowManager::MouseWheelTrigger(UIMouseWheelDir type)
{
	CsLockGuard(mouse_wheel_evt_lock_);
	if(mouse_wheel_timer_ == 0 || mouse_wheel_evts_.size() == 0)
	{
		if(mouse_wheel_timer_ == 0)
			mouse_wheel_global_speed_ = 0;
		mouse_wheel_timer_ = SetIDTimer(mouse_wheel_timer_, 0);
	}
	mouse_wheel_evts_.push_back(type);
	SS_ASSERT(mouse_wheel_timer_ != 0);
}

void UIWindowManager::ProcessAsyncNotifies()
{
	do
	{
		UINotify notify;

		{
			CsLockGuard(data_lock_);
			if(async_notifies_.empty())
				break;
			notify = async_notifies_.front();
			async_notifies_.pop();
		}

		if(notify.sender != NULL)
		{
			notify.sender->OnNotify(&notify);
		}

		if(notify.receiver != NULL)
		{
			notify.receiver->OnNotify(notify);
		}

		IUINotifyReceiverInterfaceAutoPtrs receiver_clone;

		{
			CsLockGuard(data_lock_);
			receiver_clone = notify_receivers_;
		}

		for(IUINotifyReceiverInterfaceAutoPtrs::iterator iter = receiver_clone.begin();
			iter != receiver_clone.end(); iter++)
		{
			if(*iter == NULL)
				continue;
			(*iter)->OnNotify(notify);
		}
	} while (true);
}

scoped_ref_ptr<IUIControlInterface> UIWindowManager::__FindControlForUpdate(IUIControlInterface*control, void*)
{
	SS_ASSERT(control != NULL);
	if(control->NeedUpdate())
		return control;
	return NULL;
}

_SSUIL_END
_SSL_END
